﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.CSharp;
using System.IO;
using System.CodeDom.Compiler;
using System.Reflection;

namespace HamsterSimulator.Compiler
{
    public class CodeParser
    {
        public CodeParser() { }

        public static MethodInfo[] GetMethods(string rawCode)
        {
            CompilerResults cr = GetCompilerResults(rawCode);
            Type t = GetType(cr);
            MethodInfo[] mi = t.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
            return mi;
        }

        public static MemberInfo[] GetMembers(string rawCode)
        {
            CompilerResults cr = GetCompilerResults(rawCode);
            Type t = GetType(cr);
            MemberInfo[] mi = t.GetMembers();
            return mi;
        }

        public static PropertyInfo[] GetProperties(string rawCode)
        {
            CompilerResults cr = GetCompilerResults(rawCode);
            Type t = GetType(cr);
            PropertyInfo[] pi = t.GetProperties();
            return pi;
        }

        public static CompilerErrorCollection GetErrors(string rawCode)
        {
            CompilerResults cr = GetCompilerResults(rawCode);
            return cr.Errors;
        }

        private static CompilerResults GetCompilerResults(string rawCode)
        {
            CSharpCodeProvider c = new CSharpCodeProvider();
            CompilerParameters cp = new CompilerParameters();
            cp.ReferencedAssemblies.Add("system.dll");
            cp.ReferencedAssemblies.Add("system.xml.dll");
            cp.ReferencedAssemblies.Add("system.data.dll");
            cp.ReferencedAssemblies.Add("HamsterEngine.dll");

            cp.CompilerOptions = "/t:library";
            cp.GenerateExecutable = false;
            cp.GenerateInMemory = true;
            cp.IncludeDebugInformation = false;

            string sb = GetCode(rawCode);

            CompilerResults cr = c.CompileAssemblyFromSource(cp, sb.ToString());
            return cr;
        }

        private static Type GetType(CompilerResults cr)
        {
            foreach (CompilerError ce in cr.Errors)
            {
                return null;
            }
            Assembly a = cr.CompiledAssembly;
            object o = a.CreateInstance("HamsterCodeFile.PrimiHamster");
            Type t = o.GetType();
            return t;
        }

        private static string GetCode(string rawCode)
        {
            StringBuilder sb = new StringBuilder("");
            sb.Append("using System;\n");
            sb.Append("using HamsterEngine.SimElements;\n");
            sb.Append("namespace HamsterCodeFile{\n");
            sb.Append("public class PrimiHamster : Hamster\n{\n");
            sb.Append(rawCode);
            sb.Append("}\n");
            sb.Append("}\n");

            return sb.ToString();
        }
    }

}
